package com.tools.developer.app;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.ActivityManager;
import android.content.Context;
import android.os.BatteryStats;
import android.os.BatteryStats.Timer;
import android.os.BatteryStats.Uid;
import android.os.BatteryStats.Uid.Proc;
import android.os.BatteryStats.Uid.Sensor;
import android.os.BatteryStats.Uid.Wakelock;
import android.util.SparseArray;

import com.android.internal.os.BatteryStatsImpl;
import com.tools.developer.util.CommonUtils;
import com.tools.developer.util.KLog;

public class DataUtil {

	private static final boolean DEBUG = KLog.DEG && false;

	public static Uid getUid(int uid, Context ctx) {
		SparseArray<? extends Uid> uids = (SparseArray<? extends Uid>) BatteryStatsProxy
				.getInstance(ctx).collectUidStats();
		if (uids != null && uids.size() > 0) {
			for (int i = 0; i < uids.size(); i++) {
				BatteryStatsImpl.Uid myUid = (BatteryStatsImpl.Uid) uids
						.valueAt(i);

				if (uid == myUid.getUid()) {

					return myUid;
				}
			}
		}
		return null;
	}

	/**
	 * Cpu后台占用百分比
	 * 
	 * @param uid
	 * @param ctx
	 * @return
	 */
	public static long getCpuTime(Uid app) {
		long result = 0;
		if (app != null) {

			Map<String, ? extends Proc> ProcS = app.getProcessStats();
			if (ProcS != null) {

				long cpuTime = 0;
				long foreTime = 0;
				Collection<? extends Proc> procCollection = ProcS.values();
				for (Proc proc : procCollection) {
					cpuTime += (proc
							.getSystemTime(BatteryStats.STATS_SINCE_UNPLUGGED) + proc
							.getUserTime(BatteryStats.STATS_SINCE_UNPLUGGED));
					foreTime = proc
							.getForegroundTime(BatteryStats.STATS_SINCE_UNPLUGGED);
					// Returns the total time (in 1/100 sec) spent executing in
					// system code
				}
				if (cpuTime > 0) {
					cpuTime = foreTime > cpuTime ? foreTime : cpuTime;
					long backTime = cpuTime - foreTime;
					if (DEBUG)
						KLog.i("cpuTime:" + cpuTime + "/foreTime:" + foreTime);
					result = (backTime / cpuTime) * 100;
				} else {
					result = 0;
				}
			} else {
				result = -1;
			}
		} else {
			KLog.i("app is null");
			result = -1;
		}
		return result;
	}

	/**
	 * 某款应用占用cpu的前台时间
	 * 
	 * @param uid
	 * @param ctx
	 * @return
	 */
	public static long getCpuForegroundTime(Uid app) {
		long cpuTime = 0;
		if (app != null) {

			Map<String, ? extends Proc> ProcS = app.getProcessStats();
			if (ProcS != null) {

				Collection<? extends Proc> procCollection = ProcS.values();
				for (Proc proc : procCollection) {
					cpuTime += proc
							.getForegroundTime(BatteryStats.STATS_SINCE_UNPLUGGED);
				}
			}
		} else {
			KLog.i("app is null");
		}
		return cpuTime;
	}

	public static JSONArray getSensors(Uid app, long batteryRealTime) {
		ArrayList<JSONObject> jsonList = new ArrayList<JSONObject>();
		Map<Integer, ? extends Sensor> Sensors = app.getSensorStats();
		Collection<? extends Sensor> sensorCollection = Sensors.values();
		for (Sensor s : sensorCollection) {

			Timer timer = s.getSensorTime();
			String sensorType = "sensorType null";
			switch (s.getHandle()) {
			case android.hardware.Sensor.TYPE_ACCELEROMETER:
				sensorType = "ACCELEROMETER";// 加速度
				break;
			case android.hardware.Sensor.TYPE_MAGNETIC_FIELD:
				sensorType = "MAGNETIC_FIELD";// 磁场
				break;
			case android.hardware.Sensor.TYPE_ORIENTATION:
				sensorType = "ORIENTATION";// 方向
				break;
			case android.hardware.Sensor.TYPE_GYROSCOPE:
				sensorType = "GYROSCOPE";// 陀螺仪
				break;
			case android.hardware.Sensor.TYPE_LIGHT:
				sensorType = "LIGHT";
				break;
			case android.hardware.Sensor.TYPE_PRESSURE:
				sensorType = "PRESSURE";
				break;
			case android.hardware.Sensor.TYPE_TEMPERATURE:
				sensorType = "TEMPERATURE";
				break;
			case android.hardware.Sensor.TYPE_PROXIMITY:
				sensorType = "PROXIMITY";// 距离
				break;
			case android.hardware.Sensor.TYPE_GRAVITY:
				sensorType = "GRAVITY";// 重力
				break;
			case android.hardware.Sensor.TYPE_LINEAR_ACCELERATION:
				sensorType = "TYPE_LINEAR_ACCELERATION";// 线性加速
				break;
			case android.hardware.Sensor.TYPE_ROTATION_VECTOR:
				sensorType = "TYPE_ROTATION_VECTOR";// 旋转矢量
				break;
			case Sensor.GPS:
				sensorType = "gps";// 旋转矢量
				break;
			default:
				break;
			}
			JSONObject object = new JSONObject();
			try {
				object.put("sensor_type", sensorType);
				long time = timer.getTotalTimeLocked(batteryRealTime,
						BatteryStats.STATS_SINCE_UNPLUGGED);
				object.put("sensor_total_time", time);
			} catch (JSONException e) {
				e.printStackTrace();
			}
			jsonList.add(object);
		}
		return new JSONArray(jsonList);
	}

	/**
	 * 得到某应用的传感器平均占用时间
	 * 
	 * @param app
	 * @param batteryRealTime
	 * @return
	 */
	public static long getSensorsAverage(Uid app, long batteryRealTime) {
		long time = 0;
		if (app != null) {
			Map<Integer, ? extends Sensor> Sensors = app.getSensorStats();
			if (Sensors != null) {
				Collection<? extends Sensor> sensorCollection = Sensors
						.values();
				if (sensorCollection != null && !sensorCollection.isEmpty()) {

					long size = 0;
					for (Sensor s : sensorCollection) {

						Timer timer = s.getSensorTime();
						long t = timer.getTotalTimeLocked(batteryRealTime,
								BatteryStats.STATS_SINCE_UNPLUGGED);// 得到的是微秒
						if (t > 0) {
							time += t;
							size++;
						}
					}
					if (size > 0) {

						return time / (size * 1000);// 返回豪秒
					} else {
						return 0;// 0代表使用过传感器，但是数据为0，区别于-1
					}
				}
			} else {
				time = -1;
			}
		} else {
			time = -1;
		}
		return time;
	}

	/**
	 * 
	 * @param uid
	 * @param context
	 * @return Return total PSS memory usage in kB
	 */
	public static int getTotalPss(int uid, Context context) {
		ActivityManager activityMgr = (ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE);
		int[] pidArray = CommonUtils.getPids(uid, context);
		android.os.Debug.MemoryInfo[] mems = activityMgr
				.getProcessMemoryInfo(pidArray);
		int memPSS = 0;
		if (mems == null) {
			return memPSS;
		}
		for (android.os.Debug.MemoryInfo mem : mems) {
			memPSS += mem.getTotalPss();
		}
		return memPSS;
	}

	/**
	 * 某个应用Wakelock的次数
	 * 
	 * @param uid
	 * @param batteryRealTime
	 * @param ctx
	 * @return
	 */
	public static int getWakeLocksCount(int uid, /* long batteryRealTime, */
			Context ctx) {
		Uid app = getUid(uid, ctx);
		if (app != null) {
			Map<String, ? extends Wakelock> Wakelocks = app.getWakelockStats();
			if (Wakelocks != null) {
				return Wakelocks.size();
			} else {
				return 0;
			}
		}
		return 0;
	}

	public static JSONObject getWakeLocks(Uid app, long batteryRealTime) {
		Map<String, ? extends Wakelock> Wakelocks = app.getWakelockStats();
		Collection<? extends Wakelock> wakeLockCollection = Wakelocks.values();
		long partialTotal = 0;
		long fullTotal = 0;
		long windowTotal = 0;
		for (Wakelock wake : wakeLockCollection) {
			Timer partialTimer = wake
					.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
			partialTotal += partialTimer.getTotalTimeLocked(batteryRealTime,
					BatteryStats.STATS_SINCE_UNPLUGGED);

			Timer fullTimer = wake.getWakeTime(BatteryStats.WAKE_TYPE_FULL);
			fullTotal += fullTimer.getTotalTimeLocked(batteryRealTime,
					BatteryStats.STATS_SINCE_UNPLUGGED);

			Timer windowTimer = wake.getWakeTime(BatteryStats.WAKE_TYPE_WINDOW);
			windowTotal += windowTimer.getTotalTimeLocked(batteryRealTime,
					BatteryStats.STATS_SINCE_UNPLUGGED);
		}
		JSONObject object = new JSONObject();
		try {
			if (partialTotal > 0) {
				object.put("partial_wakelock_time", partialTotal);
			}
			if (fullTotal > 0) {
				object.put("full_wakelock_time", fullTotal);
			}
			if (windowTotal > 0) {
				object.put("window_wakelock_time", windowTotal);
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return object;
	}

	/**
	 * 
	 * @param app
	 * @param batteryRealTime
	 * @return 返回-1，代表取不到该数据，需要丢弃处理
	 */
	public static long getWakeLocksAverage(Uid app, long batteryRealTime) {
		long time = 0;
		if (app != null) {

			Map<String, ? extends Wakelock> Wakelocks = app.getWakelockStats();
			if (Wakelocks != null) {
				Collection<? extends Wakelock> wakeLockCollection = Wakelocks
						.values();
				if (wakeLockCollection != null && !wakeLockCollection.isEmpty()) {

					long size = 0;
					long partialTotal = 0;
					long fullTotal = 0;
					long windowTotal = 0;
					for (Wakelock wake : wakeLockCollection) {
						Timer partialTimer = wake
								.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
						if (partialTimer != null) {
							long t = partialTimer.getTotalTimeLocked(
									batteryRealTime,
									BatteryStats.STATS_SINCE_UNPLUGGED);
							if (t > 0) {
								partialTotal += t;
								size++;
							}

						}

						Timer fullTimer = wake
								.getWakeTime(BatteryStats.WAKE_TYPE_FULL);
						if (fullTimer != null) {

							long t = fullTimer.getTotalTimeLocked(
									batteryRealTime,
									BatteryStats.STATS_SINCE_UNPLUGGED);
							if (t > 0) {
								fullTotal += t;
								size++;
							}
						}
						Timer windowTimer = wake
								.getWakeTime(BatteryStats.WAKE_TYPE_WINDOW);
						if (windowTimer != null) {

							long t = windowTimer.getTotalTimeLocked(
									batteryRealTime,
									BatteryStats.STATS_SINCE_UNPLUGGED);
							if (t > 0) {
								windowTotal += t;
								size++;
							}
						}
					}
					time = partialTotal + fullTotal + windowTotal;// 微秒
					if (size > 0) {

						time = time / size;
					} else {
						time = 0;// 代表使用过传感器，但是数据为0，区别于-1
					}
				} else {
					time = -1;
				}
			} else {
				time = -1;
			}
			return time / 1000l;// 单位毫秒ms
		} else {
			time = -1;
		}
		return time;
	}

	public static long getGpsAverage(Uid app, long batteryRealTime) {
		long result = 0;
		if (app == null) {
			result = -1;
		} else {

			Map<Integer, ? extends Sensor> sensors = app.getSensorStats();
			if (sensors == null) {
				result = -1;
			} else {

				Collection<? extends Sensor> sensorCollection = sensors
						.values();
				long time = 0;
				long size = 0;
				for (Sensor s : sensorCollection) {

					Timer timer = s.getSensorTime();
					switch (s.getHandle()) {
					case BatteryStats.Uid.Sensor.GPS:
						long t = timer.getTotalTimeLocked(batteryRealTime,
								BatteryStats.STATS_SINCE_UNPLUGGED);
						if (t > 0) {
							time += t;
							size++;
						}
						break;
					default:
						break;
					}
				}
				if (size > 0) {
					result = time / size;
				} else {
					result = 0;
				}
			}
		}
		return result;
	}

}